﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using CFProxy.Networking;


/*
 * Christiaan Rakowski
 * CFProxy - Content Filtering Proxy
 */

namespace CFProxy.FilterCode
{
	class FilterDatabase
	{
		/// <summary>
		/// The Filters in this FilterDatabase
		/// </summary>
		private HashSet<Filter> _filters = new HashSet<Filter>();

		/// <summary>
		/// The Filters in this FilterDatabase
		/// </summary>
		public HashSet<Filter> Filters
		{ 
			get { return _filters; }
			private set { _filters = value; }
		}

		public Filter HostBlackList { get; private set; }
		private ProxyServer.AppendLogDelegate appendLog;

		/// <summary>
		/// Create a FilterDatabase object
		/// </summary>
		public FilterDatabase(ProxyServer.AppendLogDelegate appendLog)
		{			
			loadFilters();
			this.appendLog = appendLog;
		}

		/// <summary>
		/// Load the filters in the Filters/ folder
		/// </summary>
		private void loadFilters()
		{
			DirectoryInfo filters = new DirectoryInfo("Filters/");
			HostBlackList = new Filter(filters.GetFiles("Host.blf")[0].FullName);

			FileInfo[] files = filters.GetFiles("*.cff");
			foreach (FileInfo file in files)
			{
				AddFilter(new Filter(file.FullName)); 
			}
		}

		/// <summary>
		/// Add a new Filter to the FilterDatabase
		/// </summary>
		/// <param name="filter">The Filter</param>
		public void AddFilter(Filter filter)
		{
			Filters.Add(filter);
		}

		/// <summary>
		/// Check if the keyword is present in the filters.
		/// If the word you entered is only a substring of one of the keywords in one of the filters it will return as a hit.
		/// </summary>
		/// <param name="keyword">The keyword</param>
		/// <returns>True if the keyword was found, False if it was not</returns>
		public bool Check(string keyword)
		{
			foreach (Filter filter in Filters)
			{
				if(filter.Check(keyword))
				{
					appendLog(String.Format("Blocked content that matched a rule in \"{0}\"", filter.Name));
					return true;
				}
			}			
			return false;
		}

		/// <summary>
		/// Check if the host entered is part of the blacklist
		/// </summary>
		/// <param name="host">The host to check</param>
		/// <returns>True if the host is blacklisted, False if it is not</returns>
		public bool CheckHost(string host)
		{
			if (HostBlackList.Check(host))
			{
				appendLog(String.Format("Host \"{0}\" is blacklisted, Connection blocked", host));
				return true;
			}
			return false;
		}
	}
}
